package org.syntaxlisp.core.utils;

import org.apache.commons.collections4.CollectionUtils;

import java.util.*;

public class ListTreeMap<K extends ListTreeVal, V> {

    private final ListTreeNode<K, V> rootEntry;

    private final Map<String, List<ListTreeNode<K, V>>> leafMap;

    public ListTreeMap() {
        rootEntry = new ListTreeNode<>(null, null, null);
        leafMap = new HashMap<>();
    }

    public boolean put (ListTreeNode<K, V> lastNode, V val) {
        return put(lastNode.getEntireKeyList(), val);
    }

    public boolean put(List<K> keyList, V val) {
        ListTreeNode<K, V> endNode = putNodes(keyList);
        boolean prevNoAdded = endNode.getVal() == null;
        if (prevNoAdded) {
            endNode.setVal(val);
/*            leafMap.computeIfAbsent(endNode.getNodeKey(), key -> new ArrayList<>())
                    .add(endNode);*/
        }
        return prevNoAdded;
    }

    private ListTreeNode<K, V> putNodes (List<K> keyList) {
        if (!CollectionUtils.isEmpty(keyList)) {
            ListTreeNode<K, V> curNode = rootEntry;
            for (K key : keyList) {
                curNode = curNode.putNextNode(key);
            }
            return curNode;
        } else {
            return rootEntry;
        }
    }

    public boolean contains(List<K> keyList) {
        Optional<ListTreeNode<K, V>> node = getNode(keyList);
        return node.map(n -> n.val != null).orElse(false);
    }

    public V get (List<K> keyList) {
        Optional<ListTreeNode<K, V>> node = getNode(keyList);
        return node.map(ListTreeNode::getVal).orElse(null);
    }

    private Optional<ListTreeNode<K, V>> getNode (List<K> keyList) {
        ListTreeNode<K, V> curNode = rootEntry;
        for (K k : keyList) {
            Optional<ListTreeNode<K, V>> nextRes = curNode.getNextNode(k);
            if (nextRes.isPresent()) {
                curNode = nextRes.get();
            } else {
                return Optional.empty();
            }
        }
        return Optional.of(curNode);
    }


    private static List<Character> stringToCharList (String val) {
        List<Character> res = new ArrayList<>(val.length());
        for (char ch : val.toCharArray()) {
            res.add(ch);
        }
        return res;
    }

}
